#ifndef _E_SHAPE_H_
#define _E_SHAPE_H_

#include "EVector.h"
#include "EQuat.h"
#include "EDebug.h"

#include "eH.h"
namespace engine
{

//------------------------------------------------------------
class EShape : public EDebugDrawable
{

public:
  enum _eShapeType
  {
    UNKNOWN_SHAPE_TYPE   = 0,
    BOX_SHAPE,
    SPHERE_SHAPE,
    CAPSULE_SHAPE,
    PLANE_SHAPE,
    TRIANGLE_MESH_SHAPE
  };
private:
  _eShapeType     m_eShapeType;

protected:
  EVector         m_vPosition;
  EQuat           m_qOrientation;
  EShape(_eShapeType eShapeType = UNKNOWN_SHAPE_TYPE);
#ifdef eDEBUG_RENDER
  SceneNode*      m_pDebugNode;
#endif

  void            endDebug       ( ManualObject* pManualObject, int& iNbRefs );
  void            drawDebug      () const {}

public:
  inline _eShapeType getType() const { return m_eShapeType; }
};

//------------------------------------------------------------
/// \todo EQuadShape
class EPlaneShape : public EShape
{
  EVector     m_vNormal;
  float       m_fD;
public:
  EPlaneShape( const EVector& vNormal, float fD );

  inline const EVector&  getNormal    () const { return m_vNormal; }
  inline float           getD         () const { return m_fD; }
};

//------------------------------------------------------------
class EBoxShape : public EShape
{
  EVector               m_vDimensions;
#ifdef eDEBUG_RENDER
  static ManualObject*  s_pDebugManualObject;
  static int            s_iNbRefs;
#endif // eDEBUG_RENDER

public:
  EBoxShape( const EVector& vDimensions );

  inline const EVector& getDimensions () const { return m_vDimensions; }
  inline void           setDimensions (const EVector& vDimensions ) { m_vDimensions = vDimensions; }

  // Debug
  /// \todo optimize the vertices declaration
  void          startDebug    ();
  void          endDebug      ();
};

//------------------------------------------------------------
class ECapsuleShape : public EShape
{
  float       m_fRadius;
  float       m_fHeight;
#ifdef eDEBUG_RENDER
  static ManualObject*  s_pDebugManualObject;
  static int            s_iNbRefs;
#endif // eDEBUG_RENDER
public:
  ECapsuleShape( float fRadius, float fHeight );

  inline float getRadius() const { return m_fRadius; }
  inline float getHeight() const { return m_fHeight; }

  // Debug
  void          startDebug    ();
  void          endDebug      ();
};

//------------------------------------------------------------
class ESphereShape : public EShape
{
  float       m_fRadius;
#ifdef eDEBUG_RENDER
  static ManualObject*  s_pDebugManualObject;
  static int            s_iNbRefs;
#endif // eDEBUG_RENDER
public:
  ESphereShape( float fRadius );

  inline float getRadius() const { return m_fRadius; }

  // Debug
  void          startDebug    ();
  void          endDebug      ();
};

//------------------------------------------------------------
class ETriangleMeshShape : public EShape
{
  const MeshPtr     &m_ogreMeshPtr;
public:
  ETriangleMeshShape( const MeshPtr& ogreMeshPtr);
  const MeshPtr&    getOgreMeshPtr() const { return m_ogreMeshPtr; }
};

} // end namespace

#endif 